<template>
    <view
        ref="triggerRef"
        id="trigger"
        class="tooltip-wrapper"
        @mousedown.stop="onStart"
        @mouseup.stop="onEnd"
        @mouseleave="onCancel"
        @touchstart.stop="onStart"
        @touchend.stop="onEnd"
        @touchcancel="onCancel"
    >
        <slot />
        <!-- 触发元素插槽 -->

        <view v-if="visible" ref="tooltipRef" id="tooltip" class="tooltip" :class="position" :style="tooltipStyle">
            <view class="tooltip-arrow" :style="{ left: arrowOffset + 'px' }" :class="position"></view>
            <view class="tooltip-content" :style="contentStyle">{{ content }}</view>
        </view>
    </view>
</template>

<script>
let currentTooltip = null; // 全局变量 互斥显示

export default {
    props: {
        content: String, //内容
        fontSize: {
            // 字体大小
            type: Number,
            default: 14,
        },
        theme: {
            // 主题
            type: String, // ['dark', 'white']
            default: 'dark',
        },
        isLongPress: {
            // 是否长按
            type: Boolean,
            default: false,
        },
        contentStyle: {
            // 卡片内容样式
            type: String,
            default: '',
        },
        longPressThreshold: {
            // 长按延时触发
            type: Number,
            default: 300,
        },
        directions: {
            // 默认方向
            type: Array,
            default: ['top', 'bottom', 'right', 'left'],
        },
        autoHideOnScroll: {
            type: Boolean,
            default: false,
        },
    },
    data() {
        return {
            pressTimer: null,
            hasEnded: false,
            visible: false,
            tooltipStyle: '', // 控制 tooltip 定位样式
            position: 'top',
            arrowOffset: 0,
            pressTimer: null,
            added: false,
            _globalClickHandler: null, // 用于存储全局点击事件处理器
            _globalScrollHandler: null, // 用于存储全局滚动事件处理器
        };
    },
    watch: {
        visible(newVal) {
            // #ifdef H5
            if (newVal) {
                // 添加全局点击监听
                this._globalClickHandler = (e) => {
                    const triggerEl = this.$refs.triggerRef?.$el || this.$refs.triggerRef;
                    const tooltipEl = this.$refs.tooltipRef?.$el || this.$refs.tooltipRef;

                    // 检查点击是否在tooltip或触发元素内部
                    const isInside =
                        (triggerEl && triggerEl.contains(e.target)) || (tooltipEl && tooltipEl.contains(e.target));

                    if (!isInside) {
                        this.hide();
                    }
                };

                // 使用setTimeout确保在事件冒泡之后添加监听
                setTimeout(() => {
                    document.addEventListener('mousedown', this._globalClickHandler);
                    document.addEventListener('touchstart', this._globalClickHandler);
                }, 10);

                // 添加滚动监听（如果启用）
                if (this.autoHideOnScroll) {
                    this._globalScrollHandler = () => {
                        this.hide();
                    };

                    // 添加滚动监听
                    window.addEventListener('scroll', this._globalScrollHandler, true);
                    document.addEventListener('scroll', this._globalScrollHandler, true);
                }
            } else if (this._globalClickHandler) {
                // 移除全局点击监听
                document.removeEventListener('mousedown', this._globalClickHandler);
                document.removeEventListener('touchstart', this._globalClickHandler);
                this._globalClickHandler = null;

                // 移除滚动监听
                if (this._globalScrollHandler) {
                    window.removeEventListener('scroll', this._globalScrollHandler, true);
                    document.removeEventListener('scroll', this._globalScrollHandler, true);
                    this._globalScrollHandler = null;
                }
            }
            // #endif
            // #ifdef MP-WEIXIN
            if (newVal) {
                // 小程序中通过页面事件处理外部点击
                this.$nextTick(() => {
                    this.bindPageEvents();
                });
            } else {
                this.unbindPageEvents();
            }
            // #endif
        },
    },
    mounted() {
        // #ifdef MP-WEIXIN
        // 监听页面滚动事件
        if (this.autoHideOnScroll) {
            this._onPageScroll = () => {
                if (this.visible) {
                    this.hide();
                }
            };

            // 获取页面实例
            const pages = getCurrentPages();
            if (pages.length) {
                const page = pages[pages.length - 1];
                if (page && page.onPageScroll) {
                    page.onPageScroll(this._onPageScroll);
                }
            }
        }
        // #endif
    },
    beforeUnmount() {
        // 组件销毁时清除全局引用
        if (currentTooltip === this) {
            currentTooltip = null;
        }
        // #ifdef MP-WEIXIN
        // 移除事件监听
        this.unbindPageEvents();

        // 移除滚动监听
        if (this._onPageScroll) {
            const pages = getCurrentPages();
            if (pages.length) {
                const page = pages[pages.length - 1];
                if (page && page.onPageScroll) {
                    page.offPageScroll(this._onPageScroll);
                }
            }
        }
        // #endif
        // #ifdef H5
        // 移除全局点击监听
        if (this._globalClickHandler) {
            document.removeEventListener('mousedown', this._globalClickHandler);
            document.removeEventListener('touchstart', this._globalClickHandler);
        }

        // 移除滚动监听
        if (this._globalScrollHandler) {
            window.removeEventListener('scroll', this._globalScrollHandler, true);
            document.removeEventListener('scroll', this._globalScrollHandler, true);
        }
        // #endif
    },
    methods: {
        onStart(e) {
            e.stopPropagation?.();

            // 普通点击触发
            if (!this.isLongPress && this.added) {
                this.hide(e);
                setTimeout(() => {
                    this.added = false;
                }, 500);
            }

            // 长按模式
            if (this.isLongPress) {
                this.pressTimer = setTimeout(() => {
                    this.show(e);
                }, this.longPressThreshold || 500);
            }
        },
        onEnd(e) {
            e.stopPropagation?.();
            clearTimeout(this.pressTimer);

            // 普通点击触发（不是长按模式，或者长按未到时间）
            if (!this.isLongPress && !this.added) {
                this.show(e);
                setTimeout(() => {
                    this.added = true;
                }, 500);
            }

            // 如果是长按模式但未触发 show（如短按中断），主动关闭
            if (this.isLongPress) {
                this.hide();
            }
        },
        onCancel(e) {
            e.stopPropagation?.();
            if (this.pressTimer) {
                clearTimeout(this.pressTimer);
            }
        },
        async show(e) {
            // 隐藏当前显示的 Tooltip（实现互斥）
            if (currentTooltip && currentTooltip !== this) {
                currentTooltip.hide();
            }
            currentTooltip = this;
            this.visible = true;
            await this.$nextTick(() => {
                this.useTooltipPosition();
            });
        },
        hide() {
            this.visible = false;
        },
        getRects() {
            return new Promise((resolve) => {
                const query = uni.createSelectorQuery().in(this);
                query.select('#tooltip').boundingClientRect();
                query.select('#trigger').boundingClientRect();
                query.exec((res) => {
                    resolve({
                        tipRect: res[0],
                        triggerRect: res[1],
                    });
                });
            });
        },
        useTooltipPosition() {
            this.getRects().then(async ({ tipRect, triggerRect }) => {
                const systemInfo = uni.getSystemInfoSync();
                const navbarHeight = systemInfo.windowTop;
                const viewport = {
                    width: systemInfo.safeArea.width,
                    height: systemInfo.safeArea.height,
                };

                // 尝试方向，按优先级选取能容纳的方向
                let chosen = 'right';
                for (const dir of this.directions) {
                    if (dir === 'top' && triggerRect.top >= tipRect.height + 10) {
                        chosen = 'top';
                        break;
                    } else if (dir === 'bottom' && viewport.height - triggerRect.bottom >= tipRect.height + 10) {
                        chosen = 'bottom';
                        break;
                    } else if (dir === 'right' && viewport.width - triggerRect.right >= tipRect.width + 10) {
                        chosen = 'right';
                        break;
                    } else if (dir === 'left' && triggerRect.left >= tipRect.width + 10) {
                        chosen = 'left';
                        break;
                    }
                }
                this.position = this.theme === 'white' ? `${chosen} white` : chosen;

                // 计算位置
                const padding = 8;
                let top, left;

                // 水平居中计算
                const horizontalCenter = triggerRect.left + triggerRect.width / 2 - tipRect.width / 2;
                // 垂直居中计算
                const verticalCenter = triggerRect.top + triggerRect.height / 2 - tipRect.height / 2 + navbarHeight;

                switch (chosen) {
                    case 'top':
                        top = triggerRect.top + navbarHeight - tipRect.height - padding;
                        left = horizontalCenter;
                        break;
                    case 'bottom':
                        top = triggerRect.bottom + navbarHeight + padding;
                        left = horizontalCenter;
                        break;
                    case 'left':
                        top = verticalCenter;
                        left = triggerRect.left - tipRect.width - padding;
                        break;
                    case 'right':
                        top = verticalCenter;
                        left = triggerRect.right + padding;
                        break;
                }

                left = Math.max(8, Math.min(left, viewport.width - tipRect.width - 8));
                top = Math.max(8, Math.min(top, viewport.height - tipRect.height - 8));

                // 计算箭头位置
                switch (chosen) {
                    case 'top':
                        this.arrowOffset = triggerRect.left + triggerRect.width / 2 - left;
                        break;
                    case 'bottom':
                        this.arrowOffset = triggerRect.left + triggerRect.width / 2 - left;
                        break;
                    case 'left':
                        this.arrowOffset = tipRect.width + 3;
                        break;
                    case 'right':
                        this.arrowOffset = -5;
                        break;
                }

                this.tooltipStyle = {
                    position: 'fixed',
                    maxWidth: '80vw',
                    left: `${left}px`,
                    top: `${top}px`,
                    fontSize: `${this.fontSize}px`,
                };
            });
        },
        bindPageEvents() {
            // 小程序中通过页面事件处理外部点击
            this._pageTouchHandler = (e) => {
                console.log(e);
                if (!this.visible) return;
                // 获取触发元素和tooltip元素
                const triggerEl = this.$refs.triggerRef;
                const tooltipEl = this.$refs.tooltipRef;

                // 获取点击位置
                const touch = e.touches?.[0] || e.changedTouches?.[0];
                if (!touch) return;

                const { pageX, pageY } = touch;

                // 检查点击是否在触发元素或tooltip内部
                const isInsideTrigger = this.checkPointInElement(pageX, pageY, triggerEl);
                const isInsideTooltip = this.checkPointInElement(pageX, pageY, tooltipEl);

                if (!isInsideTrigger && !isInsideTooltip) {
                    this.hide();
                }
            };

            // 获取当前页面实例
            const pages = getCurrentPages();
            if (pages.length) {
                const page = pages[pages.length - 1];
                if (page) {
                    page.onTouchStart = page.onTouchStart || [];
                    page.onTouchStart.push(this._pageTouchHandler);
                }
            }
        },
        unbindPageEvents() {
            // 移除页面事件监听
            if (this._pageTouchHandler) {
                const pages = getCurrentPages();
                if (pages.length) {
                    const page = pages[pages.length - 1];
                    if (page && page.onTouchStart) {
                        const index = page.onTouchStart.indexOf(this._pageTouchHandler);
                        if (index !== -1) {
                            page.onTouchStart.splice(index, 1);
                        }
                    }
                }
                this._pageTouchHandler = null;
            }
        },
        checkPointInElement(x, y, element) {
            if (!element) return false;

            // 获取元素位置
            return new Promise((resolve) => {
                const query = uni.createSelectorQuery().in(this);
                query.select(`#${element.id}`).boundingClientRect();
                query.exec((res) => {
                    if (res && res[0]) {
                        const rect = res[0];
                        resolve(
                            x >= rect.left &&
                                x <= rect.left + rect.width &&
                                y >= rect.top &&
                                y <= rect.top + rect.height
                        );
                    } else {
                        resolve(false);
                    }
                });
            });
        },
    },
};
</script>

<style lang="scss" scoped>
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}
.tooltip-wrapper {
    display: inline-block;
    position: relative;
}

.tooltip {
    background-color: #333;
    color: white;
    padding: 6px 10px;
    border-radius: 4px;
    font-size: 14px;
    z-index: 9999;
    word-break: break-word;
    white-space: normal;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
    animation: fadeIn 0.2s ease-out;
    opacity: 0;
    animation-fill-mode: forwards;
}
.tooltip {
    position: fixed;
    background-color: #333;
    color: white;
    padding: 10px 14px;
    border-radius: 6px;
    z-index: 9999;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
    max-width: 80vw;
    display: flex;
    align-items: center;
    justify-content: center;
}
.tooltip-content {
    text-align: center;
}

.tooltip.white {
    background-color: #ffffff;
    color: #333333;
    box-shadow: 0 4px 12px rgba(43, 108, 176, 0.25); /* 蓝色阴影 */
    font-weight: 500;
    // font-size: 14px;
}

.tooltip-arrow {
    width: 0;
    height: 0;
    position: absolute;

    &.top,
    &.bottom {
        left: 50%;
        top: -6px;
        transform: translateX(-50%);
    }

    &.top {
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-top: 6px solid #333;
    }

    &.bottom {
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-bottom: 6px solid #333;
    }

    &.left,
    &.right {
        top: calc(50% - 5px);
        transform: translateY(-50%);
    }

    &.left {
        border-top: 6px solid transparent;
        border-bottom: 6px solid transparent;
        border-left: 6px solid #333;
    }

    &.right {
        border-top: 6px solid transparent;
        border-bottom: 6px solid transparent;
        border-right: 6px solid #333;
    }

    /* 白色主题箭头 */
    &.white {
        &.top {
            border-top-color: #fff;
            filter: drop-shadow(0 -2px 4px rgba(43, 108, 176, 0.25));
        }
        &.bottom {
            border-bottom-color: #fff;
            filter: drop-shadow(0 2px 4px rgba(43, 108, 176, 0.25));
        }
        &.left {
            top: calc(50% - 5px);
            border-left-color: #fff;
            filter: drop-shadow(-2px 0 4px rgba(43, 108, 176, 0.25));
        }
        &.right {
            top: calc(50% - 5px);
            border-right-color: #fff;
            filter: drop-shadow(2px 0 4px rgba(43, 108, 176, 0.25));
        }
    }
}
</style>
